//
// Copyright 2008 Google Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#ifndef IRLINK_H_
#define IRLINK_H_

#define MAX_OPERANDS_STRING_LENGTH 1024
#define MAX_VERBATIM_ASSEMBLY_STRING_LENGTH 1024
#define MAX_SYMBOL_NAME_LENGTH 1024
#define MAX_SEGMENT_NAME_LENGTH 1024
#define MAX_DIRECTIVE_NAME_LENGTH 1024
#define MAX_REGISTER_NAME_LENGTH 16

#include "as.h"

struct MaoStringPiece {
  const char *data;
  int length;
};

#ifdef __cplusplus
extern "C" {
#endif
  struct symbol;
  struct _i386_insn;
  enum SymbolVisibility {
    LOCAL,
    GLOBAL,
    WEAK
  };
  enum SymbolType {
    OBJECT_SYMBOL = 0, // .type  @object
    FUNCTION_SYMBOL,   // .type  @function
    NOTYPE_SYMBOL,     // .type  @notype
    FILE_SYMBOL,       // .file
    SECTION_SYMBOL,    // .section
    TLS_SYMBOL,        // .type  @tls_object
    COMMON_SYMBOL      // .type  @common
  };

  // Link back an instruction from gas
  void link_insn(struct _i386_insn *i, size_t SizeOfInsn, int code_flag,
                 const char *line_verbatim);
  // Link back a label from gas
  void link_label(const char *name, const char *line_verbatim);
  // Link back sections from gas (i.e. data, text, bss and section directives)
  void link_section(int push, const char *name,
                   struct MaoStringPiece arguments);
  void link_subsection_directive(int subsection_number);
  // Link symbols from gas
  void link_symbol(const char *name, enum SymbolVisibility symbol_visibility,
                   const char *line_verbatim);
  // Link common symbols from gas
  void link_comm(const char *name, unsigned int common_size,
                 unsigned int common_align, const char *line_verbatim);
  // Link .type directives from gas.
  void link_type(symbolS *symbol, enum SymbolType symbol_type,
                 const char *line_verbatim);
  // Link .size directives from gas
  void link_size(const char *name, unsigned int size,
                 const char *line_verbatim);
  // Link .file directives from gas. Use NULL if no filenum is given.
  void link_file_directive(const char *name, const int *filenum);
  // Link .global/.globl directives from gas
  void link_global_directive(symbolS *symbol);
  // Link .local directives from gas
  void link_local_directive(symbolS *symbol);
  // Link .weak directives from gas
  void link_weak_directive(symbolS *symbol);
  // Link .size directives from gas
  void link_size_directive(symbolS *symbol, expressionS *expr);
  // Link .dc.b/dc.w/dc.l/.byte/.word/.long/.quad/etc directives from gas
  void link_dc_directive(int size, int rva, expressionS *expr);
  // Link .string/.string32/.ascii/.asciz/etc directives from gas
  void link_string_directive(int bitsize, int append_zero,
                             struct MaoStringPiece value);
  // Link .uleb128/.sleb128 directives from gas
  void link_leb128_directive (expressionS *expr, int sign);
  // Link .align/.balign/.p2align directives from gas
  void link_align_directive(int align, int fill_len, int fill, int max);
  void link_space_directive(expressionS *size, expressionS *fill, int mult);
  /// Link .ident directives from gas
  void link_ident_directive(struct MaoStringPiece value);
  /// Link .set/.equ directives from gas
  void link_set_directive(symbolS *symbol, expressionS *expr);
  /// Link .equiv directives from gas
  void link_equiv_directive(symbolS *symbol, expressionS *expr);
  /// Link .eqv directives from gas
  void link_eqv_directive(symbolS *symbol, expressionS *expr);
  /// Link .weakref directives from gas
  void link_weakref_directive(struct MaoStringPiece alias,
                              struct MaoStringPiece target);
  /// Link .arch directives from gas
  void link_arch_directive(struct MaoStringPiece description);
  /// Link .linefile directives from gas (generated by gas from "# NUM FILE NUM"
  void link_linefile_directive(int line_number, struct MaoStringPiece filename,
                               int num_flags, int* flag);
  void link_loc_directive(int file_number, int line_number, int column,
                          struct MaoStringPiece options[], int num_options);
  void link_allow_index_reg_directive();
  void link_disallow_index_reg_directive();
  void link_org_directive(expressionS *expr, int fill);
  // Link .code directives. For .code16gcc, the gcc flag is set to true.
  void link_code_directive(int flag_code, char gcc);
  void link_float_directive(int float_type, struct MaoStringPiece value);

  void link_popsection_directive();
  void link_previous_directive();

  void link_cons_reloc(enum bfd_reloc_code_real reloc);

  void link_hidden_directive(struct MaoStringPiece symbol_name);

  void link_fill_directive(expressionS *repeat, long size, long value);
  void link_struct_directive(long value);
  void link_incbin_directive(struct MaoStringPiece filename, long skip,
                             long count);
  void link_symver_directive(struct MaoStringPiece name,
                             struct MaoStringPiece symvername);
  void link_loc_mark_labels_directive(long value);
  void link_cfi_startproc_directive(char is_simple);
  void link_cfi_endproc_directive();
  void link_cfi_def_cfa_direcive(struct MaoStringPiece reg, long offset);
  void link_cfi_def_cfa_register_direcive(struct MaoStringPiece reg);
  void link_cfi_def_cfa_offset_direcive(long offset);
  void link_cfi_adjust_cfa_offset(long offset);
  void link_cfi_offset_direcive(struct MaoStringPiece reg, long offset);
  void link_cfi_rel_offset_direcive(struct MaoStringPiece reg, long offset);
  void link_cfi_register_direcive(struct MaoStringPiece reg1,
                                  struct MaoStringPiece reg2);
  void link_cfi_return_column_direcive(struct MaoStringPiece reg);
  void link_cfi_restore_direcive(int num_regs, struct MaoStringPiece *regs);
  void link_cfi_undefined_direcive(int num_regs, struct MaoStringPiece *regs);
  void link_cfi_same_value_direcive(struct MaoStringPiece reg);
  void link_cfi_remember_state_direcive();
  void link_cfi_restore_state_direcive();
  void link_cfi_window_save_direcive();
  void link_cfi_escape_direcive(int num_expressions, expressionS *expr[]);
  void link_cfi_signal_frame_direcive();
  void link_cfi_personality_direcive(long encoding, expressionS *expr);
  void link_cfi_lsda_direcive(long encoding, expressionS *expr);
  void link_cfi_val_encoded_addr_direcive(struct MaoStringPiece reg,
                                          long encoding,
                                          struct MaoStringPiece label);


  // Register mao object so that linking functions can access it
  void set_mao_unit(void *mao_unit);

#ifdef __cplusplus
}
#endif

#endif  // IRLINK_H_
